#pragma once
#include <iostream>
#include <functional>
#include "InetAddr.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include "Protocol.hpp"

using namespace socket_ns;
using namespace log_ns;

using process_t = std::function<std::shared_ptr<Response>(std::shared_ptr<Request>)>;

class IOService
{
public:
    IOService(process_t process) : _process(process)
    {
    }
    void IOExcute(SockSPtr sock, InetAddr addr)
    {
        std::string packagestreamqueue;
        while (true)
        {
            // 1.接收数据
            int n = sock->Recv(&packagestreamqueue);
            if (n <= 0)
            {
                LOG(INFO, "client %s quit or recv error\n", addr.AddrStr().c_str());
                break;
            }

            // 2.报文解析，提取报头和有效载荷
            std::string package = Decode(packagestreamqueue);
            if (package.empty())
                continue;

            // 3.反序列化
            auto req = Factory::BuildRequestDefault();
            req->Deserialize(package);

            // 4.任务处理
            auto res = _process(req);

            // 5.序列化应答
            std::string respjson;
            res->Serialize(&respjson);

            // 6.添加长度报头
            respjson = Encode(respjson);

            // 7.发送回复
            sock->Send(respjson);
        }
    }
    ~IOService()
    {
    }

private:
    process_t _process;
};